﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VodafoneContracts;
using System.Threading;
using System.Net;
using System.IO;

namespace VodafoneLiveTileServer
{
    public partial class Form1 : Form
    {

        List<Account> accounts;
        BasicConnection connection = null;
        VodafoneResult result = new VodafoneResult();
        System.Threading.Timer updateAccountsTimer;
        System.Threading.Timer workingTimer;

        public Form1()
        {
            InitializeComponent();


            updateAccountsTimer = new System.Threading.Timer(new TimerCallback(UpdateAccountsTimer_CallBack), null, 0, 3600000);

            UpdateAccountsTimer_CallBack(updateAccountsTimer);
        }


        public void UpdateAccountsTimer_CallBack(object s)
        {
            if (workingTimer != null)
                workingTimer.Dispose();
            GetAccounts();
        }

        public static void getHTML(string query, Action<string> callback, Action error)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(query);
                req.Method = "GET";
                req.BeginGetResponse(
                    (asyncResult) =>
                    {
                        try
                        {
                            HttpWebResponse objResponse = null;
                            StreamReader objs = null;

                            HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

                            objResponse = (HttpWebResponse)request.EndGetResponse(asyncResult);
                            objs = new StreamReader(objResponse.GetResponseStream());

                            var s = objs.ReadToEnd();
                            if (callback != null)
                                callback(s);

                            return;
                        }
                        catch (Exception e)
                        {
                            e.ToString();
                            error();
                        }
                    }
                    , req);
            }
            catch (Exception)
            {
                error();
            }
        }

        public void GetAccounts()
        {
            Console.WriteLine("updating accounts");
            string url = "http://fboscari.altervista.org/Vodafone/ManageUris.php?password=ahRohl7b";
            getHTML(url, (response) =>
            {
                AccountsParser parser = new AccountsParser(response);
                accounts = parser.getAccounts();
                if (accounts.Count == 0)
                {
                    workingTimer = null;
                }
                else
                {
                    workingTimer = new System.Threading.Timer(new TimerCallback(BeginUpdate), null, 0, 600000);
                }
            },
            () =>
            {

            });
        }

        int current = 0;

        public void BeginUpdate(object s)
        {
            if (connection != null)
                connection.Stop();
            Console.WriteLine("updating single account");
            if (accounts.Count == 0)
                return;
            if (current < 0)
                current = 0;
            if (current >= accounts.Count)
                current = 0;
            var currentAccount = accounts[current];
            //current++;
            Console.WriteLine("account: " + currentAccount.username + " - " + currentAccount.number + " - " + currentAccount.contract);

            switch (currentAccount.contract)
            {
                case VodafoneContractType.OnlyCredit:
                    connection = new CreditConnection(result, currentAccount.username, currentAccount.password, currentAccount.number,
                        !(currentAccount.othersNumbers.Count > 0 && currentAccount.number != currentAccount.othersNumbers[0]),
                        (response) =>
                        {
                            Console.WriteLine("1");
                        },
                        () =>
                        {
                            Console.WriteLine("ConnectionError");
                        },
                        () =>
                        {
                            UpdateTile(currentAccount);

                        });
                    break;

                case VodafoneContractType.MobileInternet:
                    connection = new MobileInternetConnection(result, currentAccount.username, currentAccount.password, currentAccount.number,
                        !(currentAccount.othersNumbers.Count > 0 && currentAccount.number != currentAccount.othersNumbers[0]),
                        (response) =>
                        {
                            Console.WriteLine("1");
                        },
                        () =>
                        {
                            Console.WriteLine("ConnectionError");
                        },
                        () =>
                        {
                            UpdateTile(currentAccount);

                        });
                    break;
                case VodafoneContractType.SmartZeroLimits:
                    connection = new SmartZeroLimitConnection(result, currentAccount.username, currentAccount.password, currentAccount.number,
                        !(currentAccount.othersNumbers.Count > 0 && currentAccount.number != currentAccount.othersNumbers[0]),
                        (response) =>
                        {
                            Console.WriteLine("1");
                        },
                        () =>
                        {
                            Console.WriteLine("ConnectionError");
                        },
                        () =>
                        {
                            UpdateTile(currentAccount);

                        });
                    break;
                default:
                    connection = new BasicConnection();
                    break;
            }
            connection.Start();
        }

        public void UpdateTile(Account currentAccount)
        {
            string url = "http://fboscari.altervista.org/Vodafone/UpdateLiveTile.php?";
            url += Utils.GetUpdateLiveTileArgs(result, currentAccount.contract, currentAccount.username, currentAccount.password, currentAccount.number, currentAccount.showDate);

            string tileurl = "http://fboscari.altervista.org/Vodafone/" +
                currentAccount.username + "_" +
                currentAccount.number +
                "/LiveTile.png";
            getHTML(url, s =>
            {
                //Console.WriteLine(s);

                SendLiveTileNotification(currentAccount.tileUri, tileurl, currentAccount.number);

            },
            () =>
            {

                Console.WriteLine("ConnectionError");

            });
        }

        public void SendLiveTileNotification(string uri, string url, string number)
        {
            try
            {
                // Get the URI that the Microsoft Push Notification Service returns to the Push Client when creating a notification channel.
                // Normally, a web service would listen for URIs coming from the web client and maintain a list of URIs to send
                // notifications out to.
                string subscriptionUri = uri;


                HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);

                // Create an HTTPWebRequest that posts the Tile notification to the Microsoft Push Notification Service.
                // HTTP POST is the only method allowed to send the notification.
                sendNotificationRequest.Method = "POST";

                // The optional custom header X-MessageID uniquely identifies a notification message. 
                // If it is present, the same value is returned in the notification response. It must be a string that contains a UUID.
                // sendNotificationRequest.Headers.Add("X-MessageID", "<UUID>");

                // Create the Tile message.
                string tileMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<wp:Notification xmlns:wp=\"WPNotification\">" +
                    "<wp:Tile>" +
                      "<wp:BackgroundImage>" + url + "</wp:BackgroundImage>" +
                    //"<wp:Count>" + TextBoxCount.Text + "</wp:Count>" +
                      "<wp:Title>" + number + "</wp:Title>" +
                    //"<wp:BackBackgroundImage>" + TextBoxBackBackgroundImage.Text + "</wp:BackBackgroundImage>" +
                    //"<wp:BackTitle>" + TextBoxBackTitle.Text + "</wp:BackTitle>" +
                    //"<wp:BackContent>" + TextBoxBackContent.Text + "</wp:BackContent>" +
                   "</wp:Tile> " +
                "</wp:Notification>";

                // Set the notification payload to send.
                byte[] notificationMessage = Encoding.Default.GetBytes(tileMessage);

                // Set the web request content length.
                sendNotificationRequest.ContentLength = notificationMessage.Length;
                sendNotificationRequest.ContentType = "text/xml";
                sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "token");
                sendNotificationRequest.Headers.Add("X-NotificationClass", "1");


                using (Stream requestStream = sendNotificationRequest.GetRequestStream())
                {
                    requestStream.Write(notificationMessage, 0, notificationMessage.Length);
                }

                // Send the notification and get the response.
                HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
                string notificationStatus = response.Headers["X-NotificationStatus"];
                string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
                string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];

                // Display the response from the Microsoft Push Notification Service.  
                // Normally, error handling code would be here. In the real world, because data connections are not always available,
                // notifications may need to be throttled back if the device cannot be reached.
                Console.WriteLine(notificationStatus + " | " + deviceConnectionStatus + " | " + notificationChannelStatus);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            BeginUpdate(null);
        }
    }
}
